package Align;

use vaaneeConfig qw(%C);

sub new {
	my($this) = {};

	bless $this;
	return $this;

}

sub print {
	my($this) = shift;
	my($engsen) = shift;

	my($i,$j);

	for($i=0;$i<=$#{$engsen};$i++)
	{
		if(@{$this->{'aln'}->[$i]}!=0)
		{ 
		  print "$i => ".join('_',@{$this->{'aln'}->[$i]}); 
		  print "\n";
		}

	}	
	print "Score : $this->{'score'}\n";
	print "~~~~~\n";
}

sub printEval {
	my($this) = shift;
	my($senNum) = shift;
	my($wordNum);
	my($alnPt);
	
	foreach($wordNum=0;$wordNum<@{$this->{'aln'}};$wordNum++) {
		foreach $alnPt (@{$this->{'aln'}->[$wordNum]}) {
			print "$senNum\t$wordNum\t$alnPt\n";
		}
	}
}


sub printAln {
	my($this) = shift;
	my($engsen) = shift;
	my($hinsen) = shift;

	my($i,$j);

	for($i=0;$i<=$#{$engsen};$i++)
	{
		if(@{$this->{'aln'}->[$i]}!=0)
		{ 
			my(@tgtwords);
			foreach $j (sort {$a<=>$b} @{$this->{'aln'}->[$i]}) {
				push(@tgtwords,$hinsen->[$j]->{'word'}."/".$hinsen->[$j]->{'pos'}."/".$j);
			}
			print "$engsen->[$i]->{'word'}/$engsen->[$i]->{'pos'} => ".join('_',@tgtwords); 
		}
		else
		{ print "$engsen->[$i]->{'word'} => -"; }
		print "\n";

	}	
	print "Score : $this->{'score'}\n";
	#print "---------\n";
}

sub printtabs {
	my($this) = shift;
	my($engsen) = shift;

	my($i,$j);
	#print "---------\n";
	for($i=0;$i<=$#{$engsen->{'word'}};$i++)
	{
		if($this->{'aln'}->[$i] ne "-")
		{
			if($this->{'aln'}->[$i]<=9) { print "0"; } 
			print "$this->{'aln'}->[$i] "; 
		}
		#{ print $engsen->{'word'}->[$i]."/$i => ".$this->{'aln'}->[$i]; }
		else
		{ print "-- "; }
		#{ print $engsen->{'word'}->[$i]."/$i => -"; }

	}	
	print "Score : ".&r($this->{'score'},4);
	#print "Score : $this->{'score'}\n";
	#print "---------\n";
}

sub addalign {
	my($Align) = shift;
	my($srcword) = shift;
	my($tgtword) = shift;

	push(@{$Align->{'aln'}->[$srcword]},$tgtword);
}

sub delalign {
	my($Align) = shift;
	my($srcword) = shift;

	@{$Align->{'aln'}->[$srcword]} = ();
}

sub mergealign {
	my($Align) = shift;
	my($engsen) = shift;
	my($addAlign) = shift;

	for($srcword=0;$srcword<=$#$engsen;$srcword++) {
		my(@candwords) = @{$addAlign->{'aln'}->[$srcword]};
		my(@gcandwords) = @{$Align->{'aln'}->[$srcword]};


		@{$Align->{'aln'}->[$srcword]} = ();
		@newwords = mergearrays(\@candwords,\@gcandwords);
		@{$Align->{'aln'}->[$srcword]} = @newwords;
	}

}

sub mergearrays {
	my($array1) = shift;
	my($array2) = shift;
	my(@newarray) ;
	my($newhash);
	my($i,$j);
	my($key);

	for($i=0;$i<=$#$array1;$i++) {
		$newhash->{$array1->[$i]} = 1;
	}
	for($i=0;$i<=$#$array2;$i++) {
		$newhash->{$array2->[$i]} = 1;
	}
	foreach $key (sort {$a<=>$b} keys %$newhash) {
		push(@newarray,$key);
	}
	return @newarray;
}

sub validalignment {
	my($Align) = shift;
	my($Varg) = shift;
	my($verbnum,$argnum);
	my($i);
	my($isvalid) = 1;
	my($checks) = 0;
	my($wrongs) = 0;

	for($verbnum=0;$verbnum<=$#$Varg;$verbnum++)
	{
		for($argnum=1;$argnum<=$Varg->[$verbnum]->{'Nargs'};$argnum++)
		{

			$checks ++ ;

			# If one of the arguments is a verb, check if its position matches correctly
			# with its placement as a verb
			if($Varg->[$verbnum]->{'args'}->[$argnum-1]->{'prep'}=~/^v/)
			{
				for($i=0;$i<=$#$Varg;$i++)
				{
					if($Varg->[$i]->{'position'}==$Varg->[$verbnum]->{'args'}->[$argnum-1]->{'position'})
					{ 
						if(!($Align->{'aln'}->[$verbnum]->[$argnum] == $Align->{'aln'}->[$i]->[0]))
						{ $isvalid = 0; $wrongs++; }
					}
				}
				next;
			}

			if($Align->{'aln'}->[$verbnum]->[$argnum] eq '-')
			{
				next;
			}

			if($Align->clashaln($Varg,$Align->{'aln'}->[$verbnum]->[$argnum]))
			{ $isvalid = 0; $wrongs++; next; }


			for($i=0;$i<=$#$Varg;$i++)
			{
				if($i==$verbnum)
				{
					# If the verb in question is it's own verb, then you do nothing.
					# The clash alignment thing has already been checked
				}
				else
				{
					my($L,$R);
					if($Align->{'aln'}->[$verbnum]->[$argnum]<=$Align->{'aln'}->[$verbnum]->[0])
					{ $L = $Align->{'aln'}->[$verbnum]->[$argnum]; $R = $Align->{'aln'}->[$verbnum]->[0]; }
					else
					{ $L = $Align->{'aln'}->[$verbnum]->[0]; $R = $Align->{'aln'}->[$verbnum]->[$argnum]; }
	
					#print "L = $L R = $R\n";
					#print "$Align->{'aln'}->[$i]->[0] $Align->{'leftmostpos'}->[$i] $Align->{'rightmostpos'}->[$i]\n";
		
					if($Align->{'aln'}->[$i]->[0]>=$L && $Align->{'aln'}->[$i]->[0]<=$R)
					{
						if(($Align->{'leftmostpos'}->[$i] ne "-" && $Align->{'leftmostpos'}->[$i]<$L) || ($Align->{'rightmostpos'}->[$i] ne "-" && $Align->{'rightmostpos'}->[$i] > $R))
						{ $isvalid = 0; $wrongs++; last; }
					}
					else
					{
						if($Align->{'leftmostpos'}->[$i] ne "-" && ($Align->{'leftmostpos'}->[$i]>=$L && $Align->{'leftmostpos'}->[$i]<=$R))
						{ $isvalid = 0; $wrongs++; last; }
						if($Align->{'rightmostpos'}->[$i] ne "-" && ($Align->{'rightmostpos'}->[$i]>=$L && $Align->{'rightmostpos'}->[$i]<=$R))
						{ $isvalid = 0; $wrongs++; last; }
					}
				}
			}
		}
	}

	#print "TESTING Alignment\n";
	#$Align->print($Varg);
	#print "The above alignment was valid = $isvalid\n\n\n";
	#print "Grammaticality = ".eval(1- $wrongs/$checks)."\n";

	#return $isvalid;
	if($checks == 0)
	{ return 1; }
	else
	{
		return (1 - $wrongs/$checks);
	}
}

sub clashaln {
	my($Align) = shift;
	my($Varg) = shift;
	my($alnno) = shift;
	my($i,$j);
	my($times) = 0;

	if($alnno eq "-")
	{
		return 0;
	}

	for($i=0;$i<=$#$Varg;$i++)
	{
		for($j=1;$j<=$Varg->[$i]->{'Nargs'};$j++)
		{
			if($Align->{'aln'}->[$i]->[$j] == $alnno)
			{
				$times ++;
			}
		}
	}

	if($times>1)
	{	return 1; }

	return 0;

}

sub validforadd {

	my($Align) = shift;
	my($Varg) = shift;
	my($verbnum) = shift;
	my($argnum) = shift;
	my($tword) = shift;
	my($i);

	if($argnum==0)
	{
		return 1;
	}
	if($tword eq "-")
	{
		return 1;
	}
	

	# Check if the argument is also the head of VP
	if($Varg->[$verbnum]->{'args'}->[$argnum-1]->{'prep'}=~/^v/)
	{
		for($i=0;$i<=$#$Varg;$i++)
		{
			if($Varg->[$i]->{'position'}==$Varg->[$verbnum]->{'args'}->[$argnum-1]->{'position'})
			{ 
				if($tword == $Align->{'aln'}->[$i]->[0])
				{ return 1; }
				else
				{
					 return 0; 
				}
			}
		}
	}

	#my($valid_rel) = &valid_rel($Varg->[$verbnum]->{'args'}->[$argnum-1]->{'prep'});

	if(&ontop($Align,$Varg,$tword))
	{ return 0; }
	#elsif(!($valid_rel))
	#{ return 1; }

	# If it is a normal argument, check if it is within the arg span of some other verb
	return 1;   # Testing 

	for($i=0;$i<=$#$Varg;$i++)
	{
		#$this->{'leftargs'}->[$i] = 0;
		#$this->{'rightargs'}->[$i] = 0;
		#$this->{'leftmostpos'}->[$i] = "-";
		#$this->{'rightmostpos'}->[$i] = "-";

		if($i==$verbnum)
		{
			if($Align->{'leftmostpos'}->[$i] ne "-" && $Align->{'leftmostpos'}->[$i]<=$tword && $Align->{'aln'}->[$i]->[0]>=$tword)
			{ return 0; }
			elsif($Align->{'rightmostpos'}->[$i] ne "-" && $Align->{'rightmostpos'}->[$i]>=$tword && $Align->{'aln'}->[$i]->[0]<$tword)
			{ return 0; }
		}
		else
		{
			my($L,$R);
			if($tword<=$Align->{'aln'}->[$verbnum]->[0])
			{ $L = $tword; $R = $Align->{'aln'}->[$verbnum]->[0]; }
			else
			{ $L = $Align->{'aln'}->[$verbnum]->[0]; $R = $tword; }

			if($Align->{'aln'}->[$i]->[0]>=$L && $Align->{'aln'}->[$i]->[0]<=$R)
			{
				if(($Align->{'leftmostpos'}->[$i] ne "-" && $Align->{'leftmostpos'}->[$i]<$L) || ($Align->{'rightmostpos'}->[$i] ne "-" && $Align->{'rightmostpos'}->[$i] > $R))
				{ return 0; }
			}
			else
			{
				if($Align->{'leftmostpos'}->[$i] ne "-" && ($Align->{'leftmostpos'}->[$i]>=$L && $Align->{'leftmostpos'}->[$i]<=$R))
				{ return 0; }
				if($Align->{'rightmostpos'}->[$i] ne "-" && ($Align->{'rightmostpos'}->[$i]>=$L && $Align->{'rightmostpos'}->[$i]<=$R))
				{ return 0; }
			}
		}
	}
	return 1;

}

sub ontop {
	my($Align) = shift;
	my($Varg) = shift;
	my($tword) = shift;

	my($i,$j);

	for($i=0;$i<=$#{$Align->{'aln'}};$i++)
	{
		for($j=1;$j<=$#{$Align->{'aln'}->[$i]};$j++)
		{
			if($Align->{'aln'}->[$i]->[$j]==$tword)
			{ return 1; }
		}
	}
	return 0;
}

sub valid_rel {
	my($prep) = shift;
        my(@relations) = ("subj","obj","by","on","in","into","at","for","through","with","without","of","to","after","around","during","beneath","behind","from","adj","at","from","over","about","under","before","within","against","since","until","upon","among","despite","along","beyond","than","above","near","below","onto","inside","amongst","towards","besides");
        foreach $rel (@relations)
        {
                if($rel eq $prep)
                { return 1; }
        }
        return 0;

}

sub copy {
	my($Align) = shift;
	my($Align2) = shift;
	my($i,$j);

	undef($Align->{'aln'});
	undef($Align->{'alnscr'});

	$Align->{'score'} = $Align2->{'score'};

	for($i=0;$i<=$#{$Align2->{'aln'}};$i++)
	{
		$Align->{'aln'}->[$i] = $Align2->{'aln'}->[$i];
		$Align->{'alnscr'}->[$i] = $Align2->{'alnscr'}->[$i];
	}

}

sub copy2 {
	my($Align) = shift;
	my($Align2) = shift;
	my($i,$j);

	undef($Align->{'aln'});
	undef($Align->{'alnscr'});

	$Align->{'score'} = $Align2->{'score'};

	for($i=0;$i<=$#{$Align2->{'aln'}};$i++)
	{
		for($j=0;$j<@{$Align2->{'aln'}->[$i]};$j++) {
			$Align->{'aln'}->[$i]->[$j] = $Align2->{'aln'}->[$i]->[$j];
			$Align->{'alnscr'}->[$i]->[$j] = $Align2->{'alnscr'}->[$i]->[$j];
		}
	}

}

sub getMistakes {
	my($GoldAlign) = shift;
	my($PredAlign) = shift;
	my($correct) = 0;
	my($total) = 0;
	my($mistakes) = 0;
	my($i,$j);

	$alignarr = $GoldAlign->{'aln'};
	$genalignarr = $PredAlign->{'aln'};

	for($i=0;$i<=$#$alignarr;$i++)
	{
		my(@tgtGoldWords) = @{$alignarr->[$i]};
		my(@tgtPredWords) = @{$genalignarr->[$i]};
		
		my $flag = 0;
		foreach $goldWord (@tgtGoldWords) {
			foreach $predWord (@tgtPredWords) {
				$flag = 1 if($goldWord == $predWord);
			}
			$mistakes++ if($flag==0);
		}
	}
	return $mistakes;
}

sub getnodeMistakes {
	my($GoldAlign) = shift;
	my($nodeId) = shift;
	my($PredAlign) = shift;

	my($correct) = 0;
	my($total) = 0;
	my($mistakes) = 0;
	my($i,$j);

	$alignarr = $GoldAlign->{'aln'}->[$nodeId];
	$genalignarr = $PredAlign->{'aln'}->[$nodeId];


	if(@$alignarr==0) {
	       	if(@$genalignarr==0) {
			return 0;
		}
		else {
			return 1;
		}
	}
	
	foreach $goldWord (@$alignarr) {
		my $flag = 0;
		foreach $predWord (@$genalignarr) {
			$flag = 1 if($goldWord == $predWord);
		}
		if($flag==0) {
			$mistakes++;
		}
	}

	foreach $predWord (@$genalignarr) {
		my $flag = 0;
		foreach $goldWord (@$alignarr) {
			$flag = 1 if($goldWord == $predWord);
		}
		if($flag==0) {
			$mistakes++;
		}
	}


	return $mistakes/(@$genalignarr+@$alignarr);
}

sub getCorrects {
	my($Align) = shift;
	my($GenAlign) = shift;
	my($correct) = 0;
	my($total) = 0;
	my($mistakes) = 0;
	my($i,$j);

	$alignarr = $Align->{'aln'};
	$genalignarr = $GenAlign->{'aln'};

	for($i=0;$i<=$#$alignarr;$i++)
	{
		$total++;
		if($alignarr->[$i] != $genalignarr->[$i])
		{
			$mistakes++;
		}
	}
	$correct = $total - $mistakes;
	return ($correct,$total);
}

sub r {
    my ($number,$decimals) = @_;
    return substr($number+("0."."0"x$decimals."5"),
                  0, $decimals+length(int($number))+1);
}

1;
